package com.powernode.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.powernode.constant.Constants;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Jwt工具类
 */
public class JWTUtil {

    // 1.JWT生成
    public static String createToken(String userJson, int timeoutMinute) {
        // 组装头数据(固定内容)
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        // 设置过期时间，从当前时间经过timeoutMinute分钟token失效
        // DateTime继承Date，添加了"yyyy-MM-dd HH:mm:ss"格式
        DateTime expireDate = DateUtil.offsetMinute(new Date(), timeoutMinute);

        // 构建JWT对象
        return JWT.create()
                // 组装头部
                .withHeader(header)
                // 过期时间
                .withExpiresAt(expireDate)
                // 组装负载(自定义要传输的数据)
                .withClaim("user", userJson)
                // 组装签名
                .sign(Algorithm.HMAC256(Constants.TOKEN_SECRET));
    }

    // 2.JWT解析
    public static String parseToken(String token) {
        try {
            // 使用密钥创建一个jwt的验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(Constants.TOKEN_SECRET)).build();
            // 验证jwt，得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            // 通过key名获取负载中的数据并返回
            Claim user = decodedJWT.getClaim("user");
            return user.asString();
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    // 3.JWT验证
    public static Boolean verifyToken(String token) {
        try {
            // 使用密钥创建一个jwt的验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(Constants.TOKEN_SECRET)).build();
            // 验证JWT(以是否抛出异常的方式)
            jwtVerifier.verify(token);
            return true;
        }  catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
